/*
-----------------------------------------------------------------------------
Filename:    BasicTutorial3.cpp
-----------------------------------------------------------------------------
 
This source file is part of the
   ___                 __    __ _ _    _ 
  /___\__ _ _ __ ___  / / /\ \ (_) | _(_)
 //  // _` | '__/ _ \ \ \/  \/ / | |/ / |
/ \_// (_| | | |  __/  \  /\  /| |   <| |
\___/ \__, |_|  \___|   \/  \/ |_|_|\_\_|
      |___/                              
      Tutorial Framework
      http://www.ogre3d.org/tikiwiki/
-----------------------------------------------------------------------------
*/
 
#include "TutorialApplication.h"
 
//-------------------------------------------------------------------------------------
BasicTutorial::BasicTutorial(void) {
}
//-------------------------------------------------------------------------------------
BasicTutorial::~BasicTutorial(void) { 
}
//-------------------------------------------------------------------------------------

void BasicTutorial::createScene(void) {
    mSceneMgr->setAmbientLight(Ogre::ColourValue(0.25, 0.25, 0.25));
     
    Ogre::Entity *ent = mSceneMgr->createEntity("Ninja", "ninja.mesh");
    Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("NinjaNode");
    node->attachObject(ent);

    Ogre::Light *light = mSceneMgr->createLight("Light1");
    light->setType(Ogre::Light::LT_POINT);
    light->setPosition(Ogre::Vector3(250, 150, 250));
    light->setDiffuseColour(Ogre::ColourValue::White);
    light->setSpecularColour(Ogre::ColourValue::White);

    node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode1", Ogre::Vector3(-400, 200, 400));
    node->yaw(Ogre::Degree(-45));
    node = node->createChildSceneNode("PitchNode1");
    node->attachObject(mCamera);

    node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode2", Ogre::Vector3(0, 200, 400));
    node = node->createChildSceneNode("PitchNode2");
}

void BasicTutorial::createFrameListener(void) {
    MyParent::createFrameListener();
    mCamNode = mCamera->getParentSceneNode();
    mRotate = 0.13;
    mMove = 250;
    mMouse->setEventCallback(this);
    mKeyboard->setEventCallback(this);
    mDirection = Ogre::Vector3::ZERO;
}

bool BasicTutorial::frameRenderingQueued(const Ogre::FrameEvent& evt) {
    if (mWindow->isClosed())
        return false;
    if (mShutDown)
        return false;
    mKeyboard->capture();
    mMouse->capture();
    mTrayMgr->frameRenderingQueued(evt);
    mCamNode->translate(mDirection * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
    return true;
}

bool BasicTutorial::keyPressed(const OIS::KeyEvent &evt) {
    switch (evt.key) {
    case OIS::KC_ESCAPE:
        mShutDown = true;
        break;
    case OIS::KC_1:
        mCamera->getParentSceneNode()->detachObject(mCamera);
        mCamNode = mSceneMgr->getSceneNode("CamNode1");
        mCamNode->attachObject(mCamera);
        break;
    case OIS::KC_2:
        mCamera->getParentSceneNode()->detachObject(mCamera);
        mCamNode = mSceneMgr->getSceneNode("CamNode2");
        mCamNode->attachObject(mCamera);
        break;
    case OIS::KC_UP:
    case OIS::KC_W:
        mDirection.z -= mMove;
        break;
    case OIS::KC_DOWN:
    case OIS::KC_S:
        mDirection.z += mMove;
        break;
    case OIS::KC_LEFT:
    case OIS::KC_A:
        mDirection.x -= mMove;
        break;
    case OIS::KC_RIGHT:
    case OIS::KC_D:
        mDirection.x += mMove;
        break;
    case OIS::KC_PGDOWN:
    case OIS::KC_Q:
        mDirection.y -= mMove;
        break;
    case OIS::KC_PGUP:
    case OIS::KC_E:
        mDirection.y += mMove;
    default:
        break;
    }
    return true;
}

bool BasicTutorial::keyReleased(const OIS::KeyEvent &evt) {
    switch (evt.key) {
    case OIS::KC_UP:
    case OIS::KC_W:
        mDirection.z = 0;
        break;
    case OIS::KC_DOWN:
    case OIS::KC_S:
        mDirection.z = 0;
        break;
    case OIS::KC_LEFT:
    case OIS::KC_A:
        mDirection.x = 0;
        break;
    case OIS::KC_RIGHT:
    case OIS::KC_D:
        mDirection.x = 0;
        break;
    case OIS::KC_PGDOWN:
    case OIS::KC_Q:
        mDirection.y = 0;
        break;
    case OIS::KC_PGUP:
    case OIS::KC_E:
        mDirection.y = 0;
    default:
        break;
    }
    return true;
}

bool BasicTutorial::mouseMoved(const OIS::MouseEvent &evt) {
    if (evt.state.buttonDown(OIS::MB_Right)) {
        mCamNode->yaw(Ogre::Degree(-mRotate * evt.state.X.rel), Ogre::Node::TS_WORLD);
        mCamNode->pitch(Ogre::Degree(-mRotate * evt.state.Y.rel), Ogre::Node::TS_LOCAL);
    }
    return true;
}

bool BasicTutorial::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) {
    Ogre::Light *light = mSceneMgr->getLight("Light1");
    switch (id) {
    case OIS::MB_Left:
        light->setVisible(!light->isVisible());
        break;
    default:
        break;
    }
    return true;
}

bool BasicTutorial::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id) {
    return true;
}
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
    int main(int argc, char *argv[])
#endif
    {
        // Create application object
        BasicTutorial app;
 
        try {
            app.go();
        } catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
            std::cerr << "An exception has occured: " <<
                e.getFullDescription().c_str() << std::endl;
#endif
        }
 
        return 0;
    }
 
#ifdef __cplusplus
}
#endif
